import { Asset, AssetManager, Button, error, EventHandler, instantiate, Node, Prefab, ToggleContainer } from "cc";
import { App } from "../../../App";
import { EventMgr } from "../../mgr/EventMgr";
import { ResMgr } from "../../mgr/ResMgr";
import { ViewMgr } from "../../mgr/ViewMgr";
import { btnNamePrefix, MyEvent } from "../event/MyEvent";
import { IView, TViewConfig, TViewConfigResType, ViewId } from "./IView";
import { ViewBase } from "./ViewBase";
import { ViewEvent } from "./ViewEvent";

export class IViewCtrlBaseData {
    pageIndex: number;
}

export abstract class ViewCtrlBase {

    resMgr: ResMgr;
    viewMgr: ViewMgr;
    eventMgr: EventMgr;

    node: Node = null;

    protected _view: any = null;

    get view(): ViewBase & IView {
        return this._view;
    }

    baseData: IViewCtrlBaseData = {
        pageIndex: -1
    }

    // set view(v: ViewBase & IView) {
    //     this._view = v;
    // }

    constructor(
        public config: TViewConfig,
        public dep: any[]
    ) {
        this.resMgr = App.ins.resMgr;
        this.viewMgr = App.ins.viewMgr;
        this.eventMgr = App.ins.eventMgr;
    }

    async create(): Promise<Node> {
        const { id, bundleName, prefabName, viewClazz, resArr } = this.config;

        await this.resMgr.loadBundle(id, bundleName);
        await this.resMgr.loadResArr(bundleName, resArr);
        const prefabAsset: Prefab = await this.resMgr.loadPrefab(bundleName, prefabName);

        if (!this.view) {
            this._view = new viewClazz();
            this.parseDep();
        }

        if (!this.node) {
            const node = this.createView(prefabAsset);
            this.node = node;

            this.view.viewCtrl = this;
            this.view.node = this.node;

            this.view.onCreate();
            this.onBind();
        }

        this.getNodeParent().addChild(this.node);
        this.show();
        return Promise.resolve(this.node);
    }

    protected onBind(): void {
        this.view.createMenu();
        this.bindEvent();
    }

    private _menuList: ViewId[] = null;
    getMenuList(): ViewId[] {
        if (!this._menuList) {
            const arr = this.viewMgr.getChildId(this.config.id) || [];
            this._menuList = arr.concat([]);
        }
        return this._menuList;
    }

    abstract parseDep(): void;

    private createView(prefabAsset: Prefab): Node {
        const { name } = this.config;
        const node = instantiate(prefabAsset);
        node.name = name;
        return node;
    }

    getContent(): Node {
        return this.view?.getNode("content")
    }

    private getNodeParent(): Node {
        const { layer, id } = this.config;
        return this.viewMgr.getParentCtrl(id)?.getContent() || this.viewMgr.getLayer(layer);
    }

    show(): void {
        this.onShow();
    }

    hide(): void {

        this.node?.parent && this.node.removeFromParent();
        this.onHide();
        this.resMgr.removeBundleRelation(this.config.id, this.config.bundleName);
    }

    /**只能被ResMgr调用 */
    destroy(): void {
        if (!this.node) {
            return;
        }

        /**先把自己的子界面destroy */
        const childId = this.viewMgr.getChildId(this.config.id);
        if (childId?.length) {
            for (const id of childId) {
                this.viewMgr.getCtrl(id).destroy();
            }
        }

        this.view.destroy();
        this.node = null;
    }


    onHideMyRoot(): void {

        /**先把自己的子界面 调用 */
        const childId = this.viewMgr.getChildId(this.config.id);
        if (childId?.length) {
            for (const id of childId) {
                this.viewMgr.getCtrl(id).onHideMyRoot();
            }
        }

        this.baseData.pageIndex = -1;
    }

    setMenuItemFocus(index: number, bFocus: boolean): void {
        if (bFocus) {
            if (this.baseData.pageIndex >= 0) {
                this.view.setMenuItemFocus(this.baseData.pageIndex, false);
            }
            this.baseData.pageIndex = index;
            this.view.setMenuItemFocus(this.baseData.pageIndex, true);
        } else {
            // this.view.setMenuItemFocus(this.baseData.pageIndex, true);
            console.error(" not surported yet ...   ");
        }

    }




















    /**
     * 事件相关
     */
    abstract listClickButtons(): Node[];

    listGlobalEvent(): string[] {
        return null;
    }

    listViewNodeEvent(): string[] {
        return ["node_switchPage"];
    }

    node_switchPage(e: MyEvent): void {
        // console.log('...... my event  ....... ', e);
        this.openPage(e.detail);
        e.propagationStopped = true;
    }

    private openPage(index: number): void {
        if (index == this.baseData.pageIndex) {
            return;
        }

        const childId = this.viewMgr.getChildId(this.config.id);
        let viewId = childId[index];
        this.viewMgr.openMulti(viewId);

        this.setMenuItemFocus(index, true);
    }

    protected onShow(): void {
        this.addEvent();
    }

    protected onHide(): void {
        this.removeEvent();
    }


    protected bindEvent(): void {
        const btns = this.listClickButtons() || [];
        for (const btn of btns) {
            this.addViewClickEvent(btn);
        }
        const events = this.listViewNodeEvent() || [];
        for (const eName of events) {
            this.addViewNodeEvent(eName);
        }
    }

    protected addEvent(): void {
        const gEvents = this.listGlobalEvent() || [];
        for (const gE of gEvents) {
            this.eventMgr.on(gE, this.onGlobalEvent, this);
        }

        /** 关闭界面 */
        if (this.view.btn_close) {
            this.addViewClickEvent(this.view.btn_close);
        }
    }

    protected removeEvent(): void {
        const gEvents = this.listGlobalEvent() || [];
        for (const gE of gEvents) {
            this.eventMgr.off(gE, this.onGlobalEvent, this);
        }
    }

    protected addViewClickEvent(btnNode: Node): void {
        this.view.addClickEvent(btnNode, this.onViewClick, this);
    }

    protected onViewClick(btn: Button): void {
        const name = btn.node.name;
        if (name.indexOf(btnNamePrefix) < 0) {
            console.error("wrong btn name", name);
            return;
        }
        const funcName = name.split("_")[1];
        if (this[funcName]) {
            this[funcName]();
        }
    }

    protected addViewNodeEvent(type: string): void {
        this.node.on(type, this.onViewNodeEvent, this)
    }

    protected onViewNodeEvent(e: MyEvent): void {
        const type = e.type;
        const funcName = type;
        if (this[funcName]) {
            this[funcName](e);
        }
    }

    protected addGlobalEvent(type: string): void {
        this.eventMgr.on(type, this.onGlobalEvent, this);
    }

    protected onGlobalEvent(type: string, arg1: any, arg2: any, arg3: any, arg4: any, arg5: any): void {
        /**
         * 这样写比较简单一点
         * 也可以使用switch语句
         */
        const funcName = type;
        if (this[funcName]) {
            this[funcName](arg1, arg2, arg3, arg4, arg5);
        }
    }

    close(): void {
        this.viewMgr.hide(this.config.id);
    }
}